package P107_ReflexWithDecoratorPattern;

import org.junit.Test;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;

/**
 * 使用反射增加装饰模式的普适性
 */
public class ReflexWithDecoratorPattern {

    interface Animal {
        public void doStuff();
    }

    /**
     * 老鼠
     */
    class Rat implements Animal {

        @Override
        public void doStuff() {
            System.out.println("我是一只老鼠");
        }
    }

    class DecorateAnimal implements Animal {
        //被包装的动物
        private Animal animal;

        //使用哪一个包装器
        private Class<? extends Feature> clz;

        public DecorateAnimal(Animal animal, Class<? extends Feature> clz) {
            this.animal = animal;
            this.clz = clz;
        }


        @Override
        public void doStuff() {
            InvocationHandler handler = new InvocationHandler() {

                //具体包装行为
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    Object obj = null;
                    //设置包装条件
                    if (Modifier.isPublic(method.getModifiers())) {
                        obj = method.invoke(clz.newInstance(), args);
                    }
                    animal.doStuff();
                    return obj;
                }
            };

            //当前加载器
            ClassLoader classLoader = getClass().getClassLoader();
            //动态代理,由handler决定如何包装
            Feature feature = (Feature) Proxy.newProxyInstance(classLoader, clz.getInterfaces(), handler);
            feature.load();
        }
    }

    @Test
    public void Test() {
        //定义一只老鼠
        Animal rat = new Rat();
        //增加飞行能力
        rat = new DecorateAnimal(rat, FlyFeature.class);
        //增加钻地能力
        rat = new DecorateAnimal(rat, DigFeature.class);
        rat.doStuff();
    }
}
